<template>
  <el-table
    v-loading="!getTableData?.length"
    :data="getTableData"
    style="width: 100%"
    :border="config.border ? true : false"
    :height="config.height"
    :stripe="config.stripe"
    :max-height="config.maxHeight"
    :show-summary="config.showSummary"
    :highlight-current-row="config.singleChoiceHigHlight"
    :span-method="objectSpanMethod"
    :cell-class-name="cellClassName"
    :header-cell-class-name="headerCellClassName"
    @selection-change="handleSelectionChange"
    @current-change="handleCurrentChange"
    @cell-click="cellClick"
  >
    <!-- 静态列，包括序号、多选、展开行 -->
    <template
      v-for="item in config.staticColumn"
      :key="item.type"
      :align="item.align"
    >
      <el-table-column
        v-if="item.type === 'selection'"
        :type="item.type"
        :align="item.align"
        :width="item.width"
        :selectable="selectable"
      />
      <el-table-column
        v-else-if="item.type === 'expand'"
        :type="item.type"
        :align="item.align"
        :width="item.width"
        :fixed="item.fixed"
      >
        <!-- 展开行 -->
        <template #default="scope">
          <slot
            name="expand"
            :data="scope.row"
          />
        </template>
      </el-table-column>
      <el-table-column
        v-else-if="item.type === 'index'"
        :type="item.type"
        :align="item.align"
        :width="item.width"
        :fixed="item.fixed"
        :index="indexMethod"
      />
    </template>

    <template v-for="(item, headerIndex) in header">
      <template v-if="item.children?.length">
        <el-table-column
          :key="headerIndex"
          :label="item.label"
        >
          <template v-for="(subItem, index) in item.children">
            <template v-if="subItem.children?.length">
              <el-table-column
                :key="index"
                :label="subItem.label"
              >
                <TableItem
                  v-for="_subItem in subItem.children"
                  :key="_subItem.prop"
                  v-model:search="search"
                  :data="_subItem"
                >
                  <template
                    v-if="_subItem.slotName"
                    #[_subItem.slotName||0]="{ data, currentData }"
                  >
                    <slot
                      :name="_subItem.slotName"
                      :data="data"
                      :_data="currentData"
                    />
                  </template>
                </TableItem>
              </el-table-column>
            </template>
            <TableItem
              v-else
              :key="index"
              v-model:search="search"
              :data="subItem"
            >
              <template
                v-if="subItem?.slotName"
                #[subItem.slotName||0]="{ data, currentData }"
              >
                <slot
                  :name="subItem.slotName"
                  :data="data"
                  :_data="currentData"
                />
              </template>
            </TableItem>
          </template>
        </el-table-column>
      </template>
      <TableItem
        v-else
        :key="headerIndex"
        v-model:search="search"
        :data="item"
      >
        <template
          v-if="item?.slotName"
          #[item.slotName||0]="{ data, currentData }"
        >
          <slot
            :name="item.slotName"
            :data="data"
            index=""
            :_data="currentData"
          />
        </template>
        <template
          v-if="item?.headerSlotName"
          #[item.headerSlotName||0]
        >
          <slot :name="item.headerSlotName" />
        </template>
      </TableItem>
    </template>
  </el-table>
  <!-- 分页 -->
  <!-- <br /> -->
  <Pagination
    v-if="pagination?.total&&showPagination"
    class="pagination"
    :pagination="pagination"
    @handleSizeChange="handleSizeChange"
    @handleCurrentPageChange="handleCurrentPageChange"
  />
</template>

<script lang="ts" setup>
import type {
  InitData,
  Header,
  Config,
  Pagination,
  SpanMethodProps,
} from './typing/table'
import { getMergeData } from '@/utils/tableMerge'

interface Props {
  tableData: InitData[];
  header: Header[];
  config: Config;
  selectable?: Function;
  cellClassName?: Function;
  headerCellClassName?: Function;
  pagination?: Pagination;
}
const props = defineProps<Props>()
// 总数条数变化是重新渲染分页组件，element bug
const showPagination = ref(true)
watch(
  () => props.pagination?.total,
  () => {
    showPagination.value = false
    nextTick(() => {
      showPagination.value = true
    })
  },
)

// 搜索框
const search = ref('')
const indexMethod = (index: number) => {
  if (props.config.ignoreFirstLine) {
    if (index > 0) {
      return index
    }
  } else {
    return index + 1
  }
}
const mergeData = computed(async () => {
  const { ranksMerge } = props.config
  let result: InitData[] = []
  const staticColumnLen = props.config.staticColumn?.length || 0
  if (props.tableData?.length) {
    result =
      (await (ranksMerge?.isMerge &&
        ranksMerge.data &&
        getMergeData(
          props.tableData,
          {
            ...ranksMerge.data,
          },
          staticColumnLen,
        ))) || props.tableData
  }
  return result
})

const filterData = computed(async () => {
  const { searchProp } = props.config
  const searchVal = search.value // search.value提上来写，直接写在filter里无法监控
  const val = await mergeData.value
  if (!searchProp) return val
  return val.filter((data) => !searchVal || data[searchProp].toLowerCase().includes(searchVal.toLowerCase()))
})
const getTableData = ref<InitData[]>()

watchEffect(async () => {
  getTableData.value = await filterData.value
})

const emit = defineEmits([
  'handleSelectionChange',
  'handleCurrentChange',
  'handleSizeChange',
  'handleCurrentPageChange',
  'cellClick',
])

// 多选获取数据
const handleSelectionChange = (val: InitData[]) => {
  // multipleSelection.value = val
  const hasCheckbox = props.config.staticColumn?.find(
    (item) => item.type === 'selection',
  )
  // console.log(hasCheckbox)
  if (!hasCheckbox) return () => {}
  emit('handleSelectionChange', val)
}

// 点击行获取数据
const handleCurrentChange = (val: InitData | undefined) => {
  if (!props.config?.singleChoiceHigHlight) return
  emit('handleCurrentChange', val)
}

// 点击元格事件
const cellClick = (row: any, column: any, cell: any, event: any) => {
  // console.log(row, column, cell, event)
  emit('cellClick', { row, column, cell, event })
}

// 判断某一行的checkBox是否能禁选
const selectable = (row: any, index: number) => {
  return props.selectable ? props.selectable(row) : true
}
interface DT {
  row: Object;
  rowIndex: number;
  column: Object;
  columnIndex: number;
}
// 单行表头合并，注意label向前移一位,根据项目需求来决定合并的行数
const cellClassName = (data: DT) => {
  // const { row, rowIndex, column, columnIndex } = data
  // console.log(columnIndex)
  // console.log(column)
  return props.cellClassName && props.cellClassName(data)
}
const headerCellClassName = (data: DT) => {
  // const { row, rowIndex, column, columnIndex } = data
  return props.headerCellClassName && props.headerCellClassName(data)
}

// 分页相关
const handleSizeChange = (val: number) => {
  emit('handleSizeChange', val)
}
const handleCurrentPageChange = (val: number) => {
  emit('handleCurrentPageChange', val)
}
// 合并控制
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
  // console.log(rowIndex, columnIndex)
  // console.log(row)
  // console.log(column)
  if (!props.config.ranksMerge) return
  if (row?.merge) {
    const { row: rowData, col } = row?.merge
    if (rowData) {
      const rowItem = rowData.find(
        (item: { key: string }) => item.key === column.property,
      )
      if (rowIndex === rowItem?.mergeFirstRow) {
        return {
          rowspan: rowItem?.rowLen + 1,
          colspan: 1,
        }
      }
      if (rowItem?.hidden) {
        return {
          rowspan: 0,
          colspan: 0,
        }
      }
    }

    if (col) {
      const { colLen, mergeFirstColIndex } = col
      if (columnIndex === mergeFirstColIndex) {
        return [1, colLen]
      }
      if (columnIndex > mergeFirstColIndex && columnIndex < mergeFirstColIndex + colLen) {
        return [0, 0]
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.pagination {
  margin-top: 16px;
}

:deep(.hiddenFilter) {
  .el-table__column-filter-trigger {
    display: none;
  }
}
</style>
